/**
 * @author casazaft
 */
var j2j = {};


j2j.Package = function(ns, fn){
    /*if (this != window) 
     throw Error('you can`t instance a package!');*/
    var scopePackage = Package.namespace(ns);
    if (!scopePackage.name) 
        scopePackage.name = ns;
    return {
        scope: scopePackage,
        Class: j2j.Class,
        Interface: j2j.Interface
    }
}




j2j.Package.namespace = function(ns){
    var base = window;
    
    var nss = ns.split('.');
    
    for (var i = 0; i < nss.length; i++) {
        var part = nss[i];
        if (!base[part]) 
            base[part] = {};
        else 
            if (typeof base[part] != "object") {
                throw Error("can not create namespace!")
            };
        base = base[part];
    }
    
    if (!base.exportTo) {
        base.exportTo = function(targetPackage){
            for (var p in base) {
                if (typeof base[p] != 'function') 
                    continue;
                if (!targetPackage[p]) 
                    targetPackage[p] = base[p];
            }
        }
    }
    
    
    return base;
    
}




j2j.Import = function(src){

    var destClass = j2j.Class.forName(src);
    return destClass;
    
}

j2j.Interface = function(interfaceName, implementsList){

    var currentPackage = this.scope;
    var thisInterface = currentPackage[interfaceName] = {
        check: function(destClass){
            for (var i = 0; i < this._implementsList.length; i++) {
                if (typeof destClass[this._implementsList[i]] == 'function') 
                    continue;
                else {
                    throw Error(destClass.Name + ' did not implement function ' + this._implementsList[i]);
                }
                
            }
        },
        addClass: function(className){
            this._classes.push(className);
        },
        _implementsList: [],
        _classes: []
    }
    for (var p in implementsList) {
        thisInterface._implementsList.push(p);
    }
    
    return thisInterface;
}




j2j.Class = function(className, classMeta){
    if (!this.scope) 
        throw Error('can not direct call Class function');
    if (!classMeta[className]) 
        throw Error('className did not define constructor function');
    var classConstructor = classMeta[className];
    
    var currentPackage = this.scope;
    var classRef;
    var sp = classMeta['Extends'];
    if (sp) {
        if (typeof sp == 'string') {
            sp = j2j.Class.forName(sp);
        }
        else {
        
        }
        
    }
    else {
        sp = j2j.Class.forName(j2j.Class.TOP_BASE_CLASS());
    }
    
    var sb = function(){
    
        sp.apply(this, arguments);
        return classConstructor.apply(this, arguments);
    };
    classRef = currentPackage[className] = j2j.Class.defineClass(sb, sp, classMeta);
    
    
    classRef.prototype.Name = className;
    classRef.prototype.getClass = function(){
        return classRef;
    }
    var Implements = classMeta['Implements'];
    
    if (Implements) {
        for (var i = 0; i < Implements.length; i++) {
            Implements[i].check(classRef.prototype);
            Implements[i].addClass(currentPackage.name + "." + className);
        }
        
    }
    
    classRef.exportTo = function(dest){
        dest[className] = classRef;
    }
    return classRef;
    
}

j2j.Class.defineClass = function(sb, sp, overrides){
    var oc = Object.prototype.constructor;
    if (typeof sp == 'object') {
        overrides = sp;
        sp = sb;
        sb = overrides.constructor != oc ? overrides.constructor : function(){
            sp.apply(this, arguments)
        };
    }
    
    
    var spp = sp.prototype;
    var F = function(){
    };
    var Prototype = overrides['Prototype'];
    var Statics = overrides['Statics'];
    //添加或者改写实例方法    
    F.prototype = spp;
    var sbp = sb.prototype = new F();
    if (Prototype) {
        j2j.Class.overrides(sbp, Prototype);
        
    }
    sbp.Super = spp;
    sbp.constructor = sb;
    if (spp.constructor == oc) {
        spp.constructor = sp;
    }
    
    //继承类静态方法和属性
    j2j.Class.overrides(sb, sp);
    //添加类静态属性
    
    //添加类静态方法
    if (Statics) 
        j2j.Class.overrides(sb, Statics);
    
    return sb;
}

j2j.Class.overrides = function(dest, overrides){


    for (var method in overrides) {
        if (method != 'prototype') 
            dest[method] = overrides[method];
        
    }
}

j2j.Class.TOP_BASE_CLASS = function(){
    var top_base_class = "j2j.lang.Object";
    return function(){
        return top_base_class;
    }
}()

j2j.Class.forName = function(className){
    if (typeof className != 'string') 
        throw Error('Class.forName() must pass a String parameter');
    var result = null;
    var classRealName = null;
    var container = null;
    if (className.indexOf('.') != -1) {
        var ns = className.split('.');
        
        classRealName = ns.pop();
        ns = ns.join('.');
        
        container = j2j.Package.namespace(ns);
        if (!container[classRealName] || typeof container[classRealName] != 'function') 
            throw Error('there is no Class ' + className);
        
    }
    else {
        classRealName = className;
        container = window;
        
    }
    result = container[classRealName];
    return result;
}


j2j.Package.namespace("j2j").exportTo(window);

/**
 * @author casazaft
 */
//基础类库
Package("j2j.lang").Class("Object", {
    //构造函数
    Object: function(){
 this.Super.constructor();    
    },
    Prototype: {},
    Statics: {},
    Extends: Object
})





